package srcSAT;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import lib.ArgumentValidator;

public class Graph 
{
    private List<Edge> edges;
    private HashMap<Integer, List<Integer>> neighborMap;
    private List<Integer> vertices;

    public Graph(List<Edge> edges) 
    {
        ArgumentValidator.IsNotNull("edges", edges);
        
        this.edges = edges;
        this.neighborMap = PopulateNeighborMap(edges);
        this.vertices = PopulateVertices(this.neighborMap);
    }

    public int Degree(int vertex)
    {
        return neighborMap.get(vertex).size();
    }
    
    public double Density()
    {
       double e = edges.size();
       double v = vertices.size();
       double maxVertices = v * (v-1);
       double d = e/maxVertices;
       
       return d;
    }

    public List<Edge> Edges() 
    {
        return edges;
    }
    
    public List<Integer> Neighbors(int vertex)
    {
        return neighborMap.get(vertex);
    }
    
    private HashMap<Integer, List<Integer>> PopulateNeighborMap(List<Edge> edges) 
    {
        HashMap<Integer, List<Integer>> nborMap = new HashMap<Integer, List<Integer>>();
        
        for (Edge edge : edges)
        {
            if (!nborMap.containsKey(edge.SourceNode()))
            {
                List<Integer> neighbors = new ArrayList<Integer>();
                neighbors.add(edge.DestinationNode());
                nborMap.put(
                        edge.SourceNode(),
                        neighbors);
            }
            else
            {
                nborMap.get(edge.SourceNode()).add(edge.DestinationNode());
            }
            
            if (!nborMap.containsKey(edge.DestinationNode()))
            {
                nborMap.put(edge.DestinationNode(), new ArrayList<Integer>());
            }
        }
        
        return nborMap;
    }
    
    private List<Integer> PopulateVertices(HashMap<Integer, List<Integer>> neighborMap)
    {
        return new ArrayList<Integer>(neighborMap.keySet());
    }
    
    @Override
    public String toString() 
    {
        return String.format(
                "Graph [edges=%s, vertices=%s, neighborMap=%s]",
                edges,
                Vertices(),
                neighborMap);
    }

    public List<Integer> Vertices() 
    {
        return vertices;
    }
}
